package com.tzy.parser.core.strategy;



import com.tzy.parser.core.AttributeParser;
import com.tzy.parser.exception.MetaObjNameException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import static com.tzy.parser.core.Constant.*;


/*
 * 模板定义
 *对象 a.b.c
 * 数组  a[0] a[1]
 * map  a[key]
 *
 * */
//对象模板策略
public class ObjectTemplateStrategy implements TemplateStrategy {


    private AttributeParser parser;

    public ObjectTemplateStrategy(AttributeParser parser) {
        this.parser = parser;
    }

    @Override
    public String strategyName() {
        return "object";
    }

    @Override
    public boolean canParse(String template) {

        if (isLogicalOperations(template)) {
            return false;
        }

        if (isComputationOperations(template)) {
            return false;
        }

        if (isCompareOperations(template)) {
            return false;
        }

        try {
            Double.valueOf(template.trim());
            return false;
        } catch (NumberFormatException e) {
            if (template.contains(".") || (template.contains("[") && template.contains("]"))) {
                return true;
            }
        }

        return false;
    }

    public Object parse(String template, Object meta) {


        if (template == null) {
            return null;
        }

        template = template.trim();

//        Object base = base(template);
//
//        if(base!=null){
//            return base;
//        }


        String myTemp = null;
        String nextTemp = null;


        //是否为连续表达式
        if (template.contains(".")) {
            int i = template.indexOf(".");

            myTemp = template.substring(0, i);
            nextTemp = template.substring(i + 1);
        } else {

            myTemp = template;
        }

        //解析mytype


        Object obj = meta;

        //contains 策略
        if (nextTemp != null && nextTemp.contains("contains[") && nextTemp.endsWith("]")) {
            if (obj instanceof List) {

                String contain = nextTemp.substring(9, nextTemp.length() - 1);

                Object o = parser.getStrategy("basic").parse( contain,null);

                if(o instanceof BigDecimal){
                    Double num=((BigDecimal)o).doubleValue();

                    for (Object cnum : ((List<?>) obj)) {
                        if (Double.valueOf(cnum.toString()).equals(num)) {
                            return true;
                        }
                    }

                }else {
                    return ((List) obj).contains(o);
                }

            } else {
                throw new MetaObjNameException(obj.toString() + " 不是List 无法使用 contains");
            }

        }

        if (myTemp.contains("[") && myTemp.contains("]")) {

            //解析是否为Array  List  Map
            String indexOrKey = getIndexOrKey(myTemp);
            Object o = parser.getStrategy("basic").parse( indexOrKey,null);
            if (obj instanceof Map) {

                obj = mapParse(meta, o.toString());
            } else {
                //array  list
                obj = listAndArrayParse(meta, Integer.parseInt(indexOrKey));
            }

        }


        //判断是否有下一个
        if (hasNext(nextTemp)) {

            Object o;
            //找到 obj的 getxxx 方法
            if (nextTemp.contains(".")) {
                int i = nextTemp.indexOf(".");
                //解析拿到下一个
                o = objParse(obj, nextTemp.substring(0, i));
            } else {
                o = objParse(obj, nextTemp);
            }
            return parse(nextTemp, o);
        }


        return obj;

    }



    /*
     * 是否有下一个
     * */
    private boolean hasNext(String nextTemp) {

        return nextTemp != null;
    }


    private Object listAndArrayParse(Object obj, int index) {

        if (obj instanceof List) {
            return ((List) obj).get(index);
        } else {
            return Array.get(obj, index);
        }
    }


    private Object mapParse(Object obj, Object key) {
        return ((Map) obj).get(key);
    }


    private Object objParse(Object obj, String objName) {


        if (objName.contains("[") && objName.contains("]")) {
            objName = objName.split("\\[")[0];
        }

        Class<?> aClass = obj.getClass();

        String getMethodName = "get" +
                objName.substring(0, 1).toUpperCase() + objName.substring(1);

        Object nextObj = null;
        try {
            Method method = aClass.getMethod(getMethodName);

            nextObj = method.invoke(obj);
        } catch (Exception e) {
            throw new MetaObjNameException("表达式解析错误 " + e.getMessage());
        }

        return nextObj;


    }


    private String getIndexOrKey(String myTemp) {

        String[] split = myTemp.split("\\[");

        return split[1].substring(0, split[1].length() - 1);
    }


}
